package se.topshelf.golftracker.web.controller.round;


import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Validator;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.SessionAttributes;
import se.topshelf.golftracker.core.domain.*;
import se.topshelf.golftracker.core.service.BaseService;
import se.topshelf.golftracker.core.service.PlayerService;
import se.topshelf.golftracker.web.controller.BaseEntityController;
import se.topshelf.golftracker.web.editor.BaseEntityEditor;

import javax.annotation.Resource;

@Controller
@SessionAttributes("entity")
@RequestMapping("/round")
public class RoundController extends BaseEntityController<Round> {
    static final String ALL_PLAYERS_MODEL_ATTRIBUTE = "allPlayers";
    static final String ENTITY_URL_CONTEXT_PATH = "round";
    static final String ALL_TEE_COLOURS_MODEL_ATTRIBUTE = "allTeeColours";
    static final String TEE_TIME_MODEL_ATTRIBUTE = "teeTime";


    @Resource  // Automatically set ("wired") by Spring
    private PlayerService playerService;

    public RoundController() {
        super(Round.class);
    }

    @Override
    protected String getEntityUrlContextPath() {
        return ENTITY_URL_CONTEXT_PATH;
    }

    @Override
    protected BaseService getBaseService() {
        return playerService;
    }

    @Override
    protected void addModelReferenceData(ModelMap model, Round entity) {
        model.put(ALL_PLAYERS_MODEL_ATTRIBUTE, super.fetchAllEntitiesAndBuildReferenceDataFor(Player.class));
        model.put(ALL_TEE_COLOURS_MODEL_ATTRIBUTE, TeeColour.values());
    }

    @Override
    protected void doAddParentToModel(ModelMap model, String parentId) {
        TeeTime teeTime = playerService.get(TeeTime.class, parentId);
        if (teeTime != null) {
            ((Round)model.get(ENTITY_MODEL_ATTRIBUTE)).setTeeTime(teeTime);
        } else {
            throw new IllegalArgumentException("Tried to create a new Round without attaching it to a Tee time");
        }
    }

    @Override
    protected void doRemove(Round roundToRemove) {
        TeeTime teeTime = roundToRemove.getTeeTime();
        teeTime.removeRound(roundToRemove);
        getBaseService().saveOrUpdate(teeTime);
    }

    @Override
    protected void doSave(Round entityToSave) {
        playerService.saveOrUpdate(entityToSave);
    }

    @Override
    protected String getRedirectAfterSavePath(Round savedRound) {
        return "redirect:" + "/teetime/view.htm?id=" + savedRound.getTeeTime().getId();
    }



    @Override
    protected String getRedirectAfterRemovePath(Round removedRound) {
        return "redirect:" + "/teetime/view.htm?id=" + removedRound.getTeeTime().getId();
    }

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Player.class, new BaseEntityEditor<Player>(Player.class, playerService));
        binder.registerCustomEditor(TeeTime.class, new BaseEntityEditor<TeeTime>(TeeTime.class, playerService));
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }

    @Override
    protected Validator getValidator() {
        return new RoundValidator(playerService);
    }

    // For tests
    protected void setPlayerService(PlayerService playerService) {
        this.playerService = playerService;
    }
}
